package org.example.system.incterceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.example.system.common.constant.SecurityConstants;
import org.example.system.common.result.Result;
import org.example.system.config.properties.JwtProperties;
import org.example.system.service.JwtService;
import org.example.system.service.TenantService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;


public class JwtAuthInterceptor implements HandlerInterceptor {


    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private JwtService jwtService;

    @Resource
    private JwtProperties jwtProperties;

    @Resource
    private TenantService tenantService;

    /**
     * 向客户端输出json数据
     * @param response
     * @param obj
     */
    private void writeJson(HttpServletResponse response, Object obj) {
        PrintWriter out = null;
        try {
            response.setContentType("application/json;charset=UTF-8");
            String jsonStr = objectMapper.writeValueAsString(obj);
            out = response.getWriter();
            out.write(jsonStr);
            out.flush();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if( out != null) {
                out.close();
            }
        }
    }

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler)
            throws Exception {
        // Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
        String authHeader = request.getHeader("Authorization");
        if (StringUtils.isBlank(authHeader)) {
            writeJson(response,Result.failed("401","缺少token"));
            return false;
        }
        else {
            if(!authHeader.startsWith("Bearer ")) {
                writeJson(response,Result.failed("401","token格式错误"));
                return false;
            }
            else {
                String token = authHeader.substring(7);
                try{
                    Claims claims = jwtService.parseJwt(token);
                    String openid = claims.getSubject();
                    String key = SecurityConstants.AUTH_LOGIN_KEY_PREFIX + openid;
                    ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
                    Object value = valueOperations.get(key);
                    if (value == null) {
                        writeJson(response,Result.failed("401","token已过期"));
                        return false;
                    }
                    else {
                        Long ttl = redisTemplate.getExpire(key, TimeUnit.SECONDS);
                        System.out.println("ttl = " + ttl);
                        // 当前过期时间 < 10s,自动续期 ttl Time To Live 生存时间
                        if(ttl < 10) {
                            redisTemplate.expire(key, jwtProperties.getExpire(), TimeUnit.SECONDS);
                        }
                    }
                }
                catch (Exception ex) {
                    writeJson(response,Result.failed("401","token无效"));
                    return false;
                }
            }
        }
        return true;
    }
}
